Synopsis
drvedtinit(e) struct edt *e { */your code here/* }When the system calls your drvedtinit() function, it hands the function a pointer to a structure of type edt. (This structure type is defined in the sys/edt.h header file.)
The definition of the edt type structure is:
#define NBASE 3 typedef unsigned long iopaddr_t; typedef struct iospace { unchar ios_type; /* io space type on adapter */ iopaddr_t ios_iopaddr; /* io space base address */ ulong ios_size; caddr_t ios_vaddr; /* kernel virtual address */ } iospace_t; typedef struct edt { uint_t e_bus_type; /* vme, scsi, eisa... */ unchar v_cpuintr; /* cpu to send intr to */ unchar v_setcpuintr; /* cpu field is valid */ uint_t e_adap; /* adapter */ uint_t e_ctlr; /* controller identifier */ void* e_bus_info; /* bus dependent info */ int (*e_init)(struct edt *); /* device init */ /*run-time probe*/ iospace_t e_space[NBASE]; } edt_t; #define e_base e_space[0].ios_vaddr #define e_base2 e_space[1].ios_vaddr #define e_base3 e_space[2].ios_vaddr #define e_iobase e_space[0].ios_iopaddr #define e_iobase2 e_space[1].ios_iopaddr #define e_iobase3 e_space[2].ios_iopaddrThe e_bus_type must be ADAP_GIO (defined in edt.h). The e_ctrl, v_cpuintr, and ios_type values must be 0. The (*e_init)() member is not used by drvedtinit(). (These fields are set by the kernel, and the driver does not interfere with them.) Your driver uses the e_base, e_base2, and e_base3 members:
e_base, e_base2, e_base3 | These members give your driver the base addresses as specified in the VECTOR line. Each is assigned as an unsigned long data type. |
To pass the desired interrupt CPU to the driver via the irix.sm file, use the VECTOR directive. The line
directs autoconfig (via lboot) to set the v_intrcpu field for the module's edt struct to 3 and the v_setintrcpu field to 1, indicating that v_intrcpu is valid. If no intrcpu= statement appears in the VECTOR line, v_setintrcpu is set to 0. The module's edtinit function may then use these fields to route interrupts as desired.VECTOR: module=XXX intrcpu=3
void XXXedtinit (struct edt *ep) { if (ep->setcpuintr) dest_cpu = ep->cpuintr; else dest_cpu = <some default>; ...machine-specific intr routing ... }
Note: Although lboot knows not to include in the kernel any GIO device driver for a device that is not present, it is a good idea for your drvedtinit() function to probe for its device with badaddr_val(). This allows you to write a driver that is prepared if the device has been removed from the system after the kernel has been built or when the kernel runs on another system. Continuing with this mythical GIO device driver example, its drvedtinit() function could look like:
/* equipped device table initialization function. The edt * structure is defined in edt.h. */ void gbdedtinit(struct edt *e) { int slot, val; /* Check to see if the device is present */ if(badaddr_val(e->e_base, sizeof(int), &val) || (val && GBD_MASK) != GBD_BOARD_ID) { if (showconfig) cmn_err (CE_CONT, "gbdedtinit: board not installed."); return; } /* figure out slot from base on VECTOR line in /* system file*/ if(e->e_base == (caddr_t)PHYS_TO_K1(0x1f400000)) slot = GIO_SLOT_0; else if(e->e_base == (caddr_t)0xBF600000) slot = GIO_SLOT_1; else { cmn_err (CE_NOTE, "ERROR from edtinit: Bad base address %x\n", e->e_base); return; } #ifdef IP12 /* For Indigo R3000, set up board as a /* realtime bus master */ setgioconfig(slot,0); #endif #ifdef IP20 /* For Indigo R4000, set up board as a /* realtime bus master */ setgioconfig(slot,GIO64_ARB_EXP0_RT | GIO64_ARB_EXP0_MST); #endif #ifdef IP22 /* For Indigo2, set up board as a pipelined, /* realtime bus master */ setgioconfig(slot,GIO64_ARB_EXP0_RT | GIO64_ARB_EXP0_PIPED) ; #endif /* Save the device addresses, because * they won't be available later. */ gbd_device[slot == GIO_SLOT_0 ? 0 : 1] = (struct gbd_device *)e->e_base; gbd_memory[slot == GIO_SLOT_0 ? 0 : 1] = (char *)e->e_base2; /* Where "unit_#" is any parameter passed to /* the interrupt handler (gbdintr) */ setgiovector(GIO_INTERRUPT_1,slot,gbdintr,unit_#); }